Workshop: ggplot2

Tag 1

Author

Arieja Farugie & Luca Schnatz

Published

April 12, 2023

Datensatz laden

Zunächst laden wir den Datensatz. Dieser ist als .rds Datei abgespeichert (eine R-spezifisches Datenformat), weswegen wir ihn mit dem Befehl read_rds() des readr-Packages in R einladen können. Mit glimpse() können wir einen Überblick über die verschiedenen Variablen erhalten.

library(tidyverse)
library(here)

exercise_data <- read_rds(here("data/exercise_data/clean_exercise_data.rds"))
glimpse(exercise_data)
Rows: 3,471
Columns: 32
$ id_participant                       <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11…
$ geschlecht                           <fct> weiblich, weiblich, maennlich, ma…
$ alter                                <dbl> 33, 50, 56, 61, 59, 56, 66, 25, 5…
$ familienstand                        <fct> ledig, verheirat.zusam.leb., verh…
$ nettoeinkommen_frei                  <dbl> 1800, 1100, 2500, NA, 1000, NA, 1…
$ nettoeinkommen_binned                <fct> 1750 - 1999 euro, 1000 - 1124 eur…
$ aequivalenzeinkommen                 <dbl> 1800, 2467, 1750, 4167, 1000, 466…
$ konfession                           <fct> evang.ohne freikirch, keiner reli…
$ erwerb_1                             <fct> erwerbstaetig, erwerbstaetig, erw…
$ erwerb_2                             <fct> "erwerbstaetig", "erwerbstaetig",…
$ schulabschluss                       <fct> "hochschulreife", "mittlere reife…
$ berufstaetig                         <fct> hauptberufl.ganztags, hauptberufl…
$ berufliche_stellung                  <fct> "angestellter", "angestellter", "…
$ staatsbuergerschaft                  <fct> deutschland, deutschland, deutsch…
$ deutsch_staats                       <fct> "ja", "ja", "ja", "ja", "ja", "ja…
$ bundesland                           <fct> mecklenb.-vorpommern, thueringen,…
$ ost_west                             <fct> neue bundeslaender, neue bundesla…
$ subj_schichteinstufung               <fct> mittelschicht, mittelschicht, unt…
$ bmi                                  <dbl> 23.53, 28.23, 24.77, 38.87, 30.82…
$ ps_01_gehetzt                        <int> 4, 4, 3, 2, 1, 2, 4, 2, 1, 3, 3, …
$ ps_02_niedergeschlagen               <int> 1, 4, 2, 3, 1, 2, 2, 3, 1, 1, 1, …
$ ps_03_ausgeglichen                   <int> 2, 4, 2, 2, 1, 4, 4, 3, 2, 2, 1, …
$ ps_04_energetisch                    <int> 2, 4, 2, 3, 1, 5, 2, 2, 3, 3, 3, …
$ ps_05_schmerzen                      <int> 1, 3, 1, 4, 1, 1, 4, 1, 4, 3, 1, …
$ ps_06_einsam                         <int> 1, 2, 1, 2, 1, 1, 1, 1, 3, 2, 1, …
$ ps_07_gesundeinschr_koerperlich_allg <int> 1, 3, 2, 3, 1, 1, 3, 3, 1, 1, 1, …
$ ps_08_gesundeinschr_koerperlich_art  <int> 1, 3, 2, 3, 1, 1, 4, 3, 3, 1, 1, …
$ ps_09_gesundeinschr_seelisch_allg    <int> 1, 2, 2, 2, 1, 1, 3, 1, 1, 1, 1, …
$ ps_10_gesundeinschr_seelisch_art     <int> 1, 1, 2, 2, 1, 1, 4, 1, 1, 1, 1, …
$ ps_11_einschr_sozial                 <int> 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, …
$ lebenszufriedenheit                  <dbl> 8, 8, 5, 8, 8, 8, 8, 8, 10, 8, 8,…
$ psychological_distress               <int> 16, 31, 20, 29, 11, 20, 32, 21, 2…

Basics Plots in ggplot2

An Tag 1 des Workshops geht es vor allem darum, dass Sie die wichtigsten “Basic”-Plots in ggplot2 kennenlernen und in nachfolgenden Aufgaben anwenden und ausprobieren. Das Skript ist dabei nach den verschiedenen Datentypen (kategorisch, numerisch, und die Kombinationen aus beiden) strukturiert, da es für jeden Datentyp spezifische Plots gibt, die üblicherweise verwendet werden und die Daten am besten repräsentieren.

Jede ggplot2-Abbildung fängt dabei immer mit dem gleichen leicht zu merkenden Befehl an: ggplot(). In diese Befehl können wir bereits die Daten spezifizieren, die wir visualisieren wollen und die Aesthetics definieren. Diese repräsentieren die Zuordnung von Variablen aus dem Datensatz zu verschiedenen visuellen Eigenschaften des Plots (z.B. x, y, color, fill, shape, size, etc.).

ggplot(
  data = exercise_data,
 #mapping = aes(...)
) 

Wie Sie sehen erscheint zunächst einfach ein graues Panel, denn wir haben ja noch keine Geometries und Aesthetics definiert haben.

ggplot(
  data = exercise_data,
  mapping = aes(x = alter)
  ) 

Durch das Zuordnung der x-Achse zu der Variable alter im Datensatz, erscheint nun in unserem Plot ebenfalls die Variable auf der x-Achse. Aestethics werden dabei immer über den Befehlt mapping = aes(...) definiert. Da aber noch keine Geometries festgelegt sind, werden die Daten noch nicht im Plot visualisiert.

1 Variable (Numerisch)

Wir beginnen mit einer numerische Variable (z.B. Psychologischer Distress, Alter, Body-Mass-Index).

Boxplot

Der Boxplot ist eine recht übersichtliche Art der Darstellung von Verteilungen (für mindestens ordinalskalierte Variablen). Als praktisches Beispiel wollen wir uns anschauen wie die Variable psychologischer Distress in den Daten verteilt ist. Wie bereits können wir bereits in den ggplot()-Befehl den Datensatz und die Aestethics definieren. Wenn wir einen vertikalen Boxplot benutzen wollen, müssen wir dabei in den Aesthetics aes(y = psychological_distress) eingeben, da wir die y-Achse der Variable psychologischer Distress zuordnen. Danach können wir über den Befehl geom_boxplot() den Boxplot erstellen.

ggplot(
  data = exercise_data,
  aes(y = psychological_distress)
  ) +
  geom_boxplot()
Warning: Removed 25 rows containing non-finite values (`stat_boxplot()`).

ggplot(
  data = exercise_data,
  aes(x = psychological_distress)
  ) +
  geom_boxplot()
Warning: Removed 25 rows containing non-finite values (`stat_boxplot()`).

Histogramm

Ein Histogramm können wir ganz analog zu dem Boxplot definieren, indem wir einfach den Befehl geom_boxplot() austauschen mit dem Befehl geom_histogram(). Wichtig zu beachtet bei Histogrammen ist, dass Anzahl der Kategorien (bins) eine Auswirkung auf die Optik des Plots hat. Es lohnt sich also verschiedene Bingrößen bzw. Anzahl an Bins auszuprobieren und die Anzahl zu wählen, die die Daten am besten repräsentiert. Wir können die Anzahl an Bins mit dem Argument bins = ... spezifizieren und die Bingröße über das Argument binwidth = ....

ggplot(
  data = exercise_data,
  aes(x = psychological_distress)
  ) +
  geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Warning: Removed 25 rows containing non-finite values (`stat_bin()`).

ggplot(
  data = exercise_data,
  aes(x = psychological_distress)
  ) +
  geom_histogram(bins = 10)
Warning: Removed 25 rows containing non-finite values (`stat_bin()`).

ggplot(
  data = exercise_data,
  aes(x = psychological_distress)
  ) +
  geom_histogram(bins = 40)
Warning: Removed 25 rows containing non-finite values (`stat_bin()`).

Density-Plot

Eine weitere Methode, um die Verteilung einer numerischen Variable zu visualisieren, ist der Density-Plot. Dabei wird in einem Density-Plot eine Kernel-Dichte-Schätzung verwendet, um die Wahrscheinlichkeitsdichtefunktion der Variablen darzustellen. In ggplot2 können wir sehr einfach einen Density-Plot mit die Funktion geom_density() definieren. Sie sehen, dass die Geometries (also die Spezifikation, welcher Art des Plots verwendet werden soll) in ggplot2 alle mit geom_… beginnen. So sind sie recht einfach einzuprägen. Bei Density-Plots können wir mit dem Argument bw = ... die Bandwith definieren, wie sehr sich der Plot an unserer Daten anpassen soll (wie genau die Dichte der Verteilung entsprechen soll). Ggplot2 wählt hier meistens schon gute Default-Werte, probieren Sie aber im Zweifel trotzdem verschiedene Werte aus, um zu schauen wie sich der Plot verändert.

ggplot(
  data = exercise_data,
  aes(x = psychological_distress)
  ) +
  geom_density()
Warning: Removed 25 rows containing non-finite values (`stat_density()`).

ggplot(
  data = exercise_data,
  aes(x = psychological_distress)
  ) +
  geom_density(bw = .4)
Warning: Removed 25 rows containing non-finite values (`stat_density()`).

ggplot(
  data = exercise_data,
  aes(x = psychological_distress)
  ) +
  geom_density(bw = 3)
Warning: Removed 25 rows containing non-finite values (`stat_density()`).

1 Variable (Kategorisch)

Als nächsten gehen über zu Visualisierungen für eine kategorische Variable (z.B. Geschlecht, Bundesland, etc.). Hier bieten sich vor allem drei verschiedene Plots an: Häufigkeitdiagramme (Barplots) und Kuchendiagramme (Pie-Charts).

Barplot

Die Verwendung von Barplots ist insbesondere dann sinnvoll, wenn wir die Häufigkeit (absolut oder relativ) einer kategorischen Variable darstellen wollen. Wir müssen dafür nur in den Aethetics die kategorische Variable entwender der x oder y-Achse zuordnen (mapping = aes(x/y = …)). Danach können wir mit dem Befehl geom_bar() den Barplot definieren. Das Argument stat = "count" ist dabei der Default, müsste also theoretisch nicht spezifiziert werden. Es macht allerdings den Code expliziter und dadurch verständlicher. Wenn wir statt absoluter Häufigkeiten relative Häufigkeiten darstellen wollen, müssen wir dies in den Aesthetics bereits definieren. Die Schreibweise y = after_stat(count/sum(count)) ist dabei folgendermaßen zu lesen: Auf der y-Achse soll die Anzahl einer Kategorie durch die Summe aus der Anzahl aller Kategorien geteilt werden (relative Häufigkeit).

ggplot(
  data = exercise_data,
  mapping = aes(x = subj_schichteinstufung)
  ) + 
  geom_bar(stat = "count")

ggplot(
  data = exercise_data,
  mapping = aes(y = subj_schichteinstufung)
  ) + 
  geom_bar(stat = "count")

# relative Häufigkeit
ggplot(
  data = exercise_data,
  mapping = aes(x = subj_schichteinstufung,
                y = after_stat(count/sum(count)))
  ) + 
  geom_bar()

Kuchendiagramm (Pie-Chart)

Ein Kuchendiagramm ist in ggplot2 letzendlich nur ein abgewandelter Barplot, bei dem die Säulen des Plots einem polaren Koordinatensystem zugeordnet werden. Bevor wir das Kuchendiagram visualisieren können, müssen wir in diesem Fall die Häufigkeiten der Kategorien (z.B. der Konfession) schon im Vorhhinein berechen. Dies geht sehr leicht mit der Funktion count() aus dem dplyr-Package. Danach können wir die Häufigkeit der Kategorien (die Variable n) der y-Achse in den Aesthetics zuordnen. Mit der Aestethic fill = konfession wird die Variable in unserem Datensatz über die Farbe im Plot dargestellt. Mittels coord_polar(theta = "y") wird das kartesische Koordinatensystem in ein polares Koordinatensystem umgewandelt, um das Kuchendiagram zu erstellen.

exercise_data %>%
  count(konfession) %>% # Bestimmung der Häufigkeiten der Konfession
  drop_na(konfession) %>% # NAs rausschmeißen
  ggplot(
    data = .,
    mapping = aes(x = "", 
                  y = n, # Häufigkeit
                  fill = konfession) # Kategorie
  ) + 
  geom_bar(stat = "identity") + # "identity" statt "count"
  coord_polar(theta = "y") 

2 Variablen (Numerisch, Numerisch)

Nachdem Sie einige Plots für die Visualisierung für nur eine Variable (numerisch oder kategorisch) kennengelernt haben, wollen wir uns als nächstes der Visualisierung von zwei Variablen widmen. Wir starten dabei mit der Visualisierung zwei numerischer Variablen.

Scatterplot

Der klassische Plot, um zwei numerische Variablen zu visualisieren, ist der Scatterplot oder auch Streudiagramm. Die Geometry, die Sie dafür benötigen ist geom_point(). Wir definieren einfach die beiden Variablen, die wir visualisieren wollen in den Aestethics über aes(x = ..., y = ...).

ggplot(
  data = exercise_data,
  mapping = aes(x = alter,
                y = bmi)
  ) +
  geom_point()  
Warning: Removed 55 rows containing missing values (`geom_point()`).

# Anpassungsmöglichkeiten 
ggplot(
  data = exercise_data,
  mapping = aes(x = alter,
                y = bmi)
  ) +
  geom_point(alpha = 0.3) # Durchsichtigkeit der Punkte (von alpha = 0-1)
Warning: Removed 55 rows containing missing values (`geom_point()`).

ggplot(
  data = exercise_data,
  mapping = aes(x = alter,
                y = bmi)
  ) +
  geom_point(size = 0.5) # Größe der Punkte
Warning: Removed 55 rows containing missing values (`geom_point()`).

ggplot(
  data = exercise_data,
  mapping = aes(x = alter,
                y = bmi)
  ) +
  geom_point(color = "darkblue") # Farbe der Punkte
Warning: Removed 55 rows containing missing values (`geom_point()`).

2 Variablen (Kategorisch, Kategorisch)

Um zwei kategorische Variablen zu visualisieren, bietet sich ebenfalls ein Barplot an. Wir ordnen dabei die eine kategorische Variable eine Achse des Koordinatensystems zu (x oder y) und ordnen die andere Variable der Aesthetic fill oder color zu. Dabei gibt es verschiedenen Möglichkeiten, wie die Säulen visualisiert werden. Entweder können diese nebeneinander stehen (position = position_dodge(width = 1)) oder aufeinander stehen (position = position_stack()).

Alternativ zu einer Farbzuordnung können Sie auch zwei kategorische Variablen visualisieren, indem Sie mehrere Panels verwenden. Dies kann vor allem bei sehr unübersichtlichen Plots mit vielen Kategorien sinnvoll sein. Mehrere Panels/Facets können Sie definieren über die Funktion facet_wrap() (oder facet_grid(), die hier nicht näher spezifiziert wird). Sie müssen dabei in diesen Funktionen angeben, auf Basis welcher Variable mehrere Panels erstellt werden sollen. Sie können dafür entweder die Schreibweise facets = ~geschlecht oder facets = vars(geschlecht) verwenden

# Zweite Variable mittels Farbzuordnung
ggplot(
  data = exercise_data,
  mapping = aes(x = subj_schichteinstufung, fill = geschlecht)
  ) + 
  geom_bar(stat = "count", position = position_dodge(width = 1))

ggplot(
  data = exercise_data,
  mapping = aes(x = subj_schichteinstufung, fill = geschlecht)
  ) + 
  geom_bar(stat = "count", position = position_stack())

# Definition von verschiedenen Panels statt Farbzuordnung

ggplot(
  data = exercise_data,
  mapping = aes(x = subj_schichteinstufung)
  ) + 
  geom_bar(stat = "count", position = position_dodge(width = 1)) + 
  facet_wrap(facets = ~geschlecht) # mehrere Panels

ggplot(
  data = exercise_data,
  mapping = aes(x = geschlecht)
  ) + 
  geom_bar(stat = "count", position = position_dodge(width = 1)) + 
  facet_wrap(facets = ~subj_schichteinstufung) # Alternativ Schreibweise: facets = vars(subj_schichteinstufung)

2 Variablen (Numerisch, Kategorisch)

Für eine Visualisierung mit einer numerischen und einer kategorischen Variable können Sie auf die Plots, die Sie schon zum Teil Visualisierung mit einer numerischen Variable zurückgreifen. Für das Beispiel des Boxplots ordnen Sie einfach zusätzlich in den Aesthetics die kategorische Variable entweder x oder y zu. Wenn Sie einen Density-Plot verwenden wollen, können sie die Aesthetics fill oder color der kategorischen Variable zuordnen.

ggplot(
  data = exercise_data,
  mapping = aes(x = subj_schichteinstufung,
                y = psychological_distress)
  ) + 
  geom_boxplot()
Warning: Removed 25 rows containing non-finite values (`stat_boxplot()`).

ggplot(
  data = exercise_data,
  mapping = aes(x = psychological_distress,
                fill = subj_schichteinstufung)
  ) + 
  geom_density(alpha = 0.5)
Warning: Removed 25 rows containing non-finite values (`stat_density()`).

# Exkurs
library(ggridges)
ggplot(data = exercise_data,
       mapping = aes(x = psychological_distress,
                     y = subj_schichteinstufung,
                     fill = subj_schichteinstufung)) + 
  geom_density_ridges()
Picking joint bandwidth of 2.39
Warning: Removed 25 rows containing non-finite values
(`stat_density_ridges()`).

Mehr als zwei Variablen

Für mehr können Sie bisher vorgestellten Konzepte gemeinsam kombinieren. x, y, color, fill, shape können verschiedenen Variablen zugeordnet werden. Ebenfalls können Sie die vorher vorgestellten Multipanel-Funktion nutzen (facet_wrap oder facet_grid).

ggplot(
  data = exercise_data,
  mapping = aes(x = alter,
                y = bmi,
                color = geschlecht,
                shape = geschlecht)
) + 
  geom_point()
Warning: Removed 55 rows containing missing values (`geom_point()`).

ggplot(
  data = exercise_data,
  mapping = aes(x = alter,
                y = bmi)
                
  ) + 
  geom_point() + 
  facet_grid(cols = vars(geschlecht)) 
Warning: Removed 55 rows containing missing values (`geom_point()`).

ggplot(
  data = exercise_data,
  mapping = aes(x = alter,
                y = bmi,
                color = geschlecht)
) + 
  geom_point() + 
  facet_grid(cols = vars(geschlecht)) 
Warning: Removed 55 rows containing missing values (`geom_point()`).

ggplot(
  data = exercise_data,
  mapping = aes(x = subj_schichteinstufung,
                y = psychological_distress,
                fill = geschlecht)
  ) + 
  geom_boxplot()
Warning: Removed 25 rows containing non-finite values (`stat_boxplot()`).

ggplot(
  data = exercise_data,
  mapping = aes(x = subj_schichteinstufung,
                y = psychological_distress)
  ) + 
  geom_boxplot() + 
  facet_wrap(~geschlecht)
Warning: Removed 25 rows containing non-finite values (`stat_boxplot()`).